#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <time.h>
////

#ifdef _WIN32
#define strcasecmp _stricmp
#endif

struct RandomTable {
  unsigned int data[4096 / sizeof(unsigned int)];
};

void RandFill(RandomTable &table) {
  for (auto &i : table.data) {
    i = rand();
  }
}

bool FlushBigFile(const std::string &file, uint64_t size) {
  auto fp = fopen(file.c_str(), "w+");
  if (fp == nullptr) {
    fprintf(stderr, "Open File: %s\n", strerror(errno));
    return false;
  }
  auto n = size / sizeof(RandomTable);
  if (size % sizeof(RandomTable) != 0) {
    n += 1;
  }
  RandomTable table;
  uint64_t ws = 0;
  srand((unsigned)time(nullptr));
  for (size_t i = 0; i < n; i++) {
    RandFill(table);
    auto x = fwrite(&table, sizeof(table), 1, fp);
    fflush(fp);
    ws += x * sizeof(table);
  }
  fclose(fp);
  fprintf(stderr, "Flush %s size: %" PRIu64 " KB\n", file.c_str(), ws / 1024);
  return true;
}

int main(int argc, char const *argv[]) {
  /* code */
  if (argc < 3) {
    fprintf(stderr, "usage: %s file size\nExample:%s example.bin 10KB\n",
            argv[0], argv[0]);
    return 1;
  }
  char *c;
  auto sz = strtol(argv[2], &c, 10);
  bool result = false;
  if (c == nullptr || *c == 0 || strcasecmp(c, "b") == 0) {
    result = FlushBigFile(argv[1], sz);
  } else if (strcasecmp(c, "kb") == 0) {
    result = FlushBigFile(argv[1], sz * 1024);
  } else if (strcasecmp(c, "mb") == 0) {
    result = FlushBigFile(argv[1], sz * 1024 * 1024);
  } else if (strcasecmp(c, "gb") == 0) {
    result = FlushBigFile(argv[1], sz * 1024 * 1024 * 1024);
  } else {
    fprintf(stderr, "Not supported size unit: %s [size unit: B,KB,MB,GB]\n", c);
    return 2;
  }
  if (!result) {
    fprintf(stderr, "Flush %s failed\n", argv[1]);
    return 1;
  }
  fprintf(stderr, "Flush %s success\n", argv[1]);
  return 0;
}
